namespace Example
{
    using System;
    using System.Net;
    using Example.Properties;
    using SimpleWebServices.Data;
    using SimpleWebServices.Net;
    using SimpleWebServices.Web;
    using SimpleWebServices.Web.UI.Html.Elements;
    using Xunit;

    public sealed class ContactFacts
    {
        private static readonly Resource _resource = new GenericResource
        {
            Description = "This is the contact page of the example website.",
            Location = "/contact",
            Title = "Contact Page",
            Links =
            {
                new Link { Relationship = "canonical", Hyperlink = new Uri("http://example.simplewebservices.org/contact.en.html") }
            }
        }
        .ApplyDefaultValues<GenericResource>();

        [Fact]
        public void Get_LanguageNegotiation()
        {
            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact")
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .IsLanguageNegotiationToEnglish()
                .HasNoCookies()
                .Result);
        }

        [Fact]
        public void Get_ContentNegotiation_html()
        {
            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact.en")
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .IsContentNegotiationToTextHtml()
                .HasNoCookies()
                .Result);
        }

        [Fact]
        public void Get_ContentNegotiation_xhtml()
        {
            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact.en")
                .Accept("application/xhtml+xml")
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .IsSeeOther("http://example.simplewebservices.org/contact.en.xhtml")
                .HasNoCookies()
                .Result);
        }

        [Fact]
        public void Get_HtmlRepresentation()
        {
            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact.en.html")
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .Is(HttpStatusCode.OK)
                .HasCacheControlPublic()
                .WithExpires()
                .HasContentLanguageOfEnglish()
                .HasContentMD5()
                .ResponseIsTextHtml(_resource)
                .HasStyleSheetLink(Settings.Default.Stylesheet)
                .HasRobotsTag("FOLLOW,INDEX")
                .Evaluate<double>(1, Analytics.Xpath)
                .Evaluate<double>(0, "count(//p[@id='confirmation'])")
                .Evaluate<double>(1, "count(//form[@method='post'][@action='/contact'])")
                .Evaluate<double>(1, "count(//label[@for='name'][@accesskey='n'])")
                .Evaluate<double>(1, "count(//input[@id='name'][@type='text'][@value=''])")
                .Evaluate<double>(1, "count(//label[@for='email'][@accesskey='e'])")
                .Evaluate<double>(1, "count(//input[@id='email'][@type='text'][@value=''])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/legend[@id='legend-choice'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/label[@for='choice:1'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/input[@type='radio'][@id='choice:1'][@name='choice'][@value='1'][not(@checked)])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/label[@for='choice:2'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/input[@type='radio'][@id='choice:2'][@name='choice'][@value='2'][not(@checked)])")
                .Evaluate<double>(1, "count(//label[@for='terms_and_conditions'][@accesskey='t'])")
                .Evaluate<double>(1, "count(//input[@id='terms_and_conditions'][@type='checkbox'][not(@checked)])")
                .Evaluate<double>(1, "count(//label[@for='message'][@accesskey='m'])")
                .Evaluate<double>(1, "count(//textarea[@id='message'])")
                .Evaluate<double>(1, "count(//input[@type='submit'])")
                .Evaluate<double>(1, "count(//a[@id='reset'][@href='/contact'])")
                .HasNoCookies()
                .HasContentLocation("http://example.simplewebservices.org/contact.en.html")
                .Result);
        }

        [Fact]
        public void Get_XhtmlRepresentation()
        {
            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact.en.xhtml")
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .Is(HttpStatusCode.OK)
                .HasCacheControlPublic()
                .WithExpires()
                .HasContentLanguageOfEnglish()
                .HasContentMD5()
                .ResponseIsApplicationXhtml(_resource)
                .HasStyleSheetLink(Settings.Default.Stylesheet)
                .HasRobotsTag("FOLLOW,INDEX")
                .Evaluate<double>(1, Analytics.Xpath)
                .Evaluate<double>(0, "count(//p[@id='confirmation'])")
                .Evaluate<double>(1, "count(//form[@method='post'][@action='/contact'])")
                .Evaluate<double>(1, "count(//label[@for='name'][@accesskey='n'])")
                .Evaluate<double>(1, "count(//input[@id='name'][@type='text'][@value=''])")
                .Evaluate<double>(1, "count(//label[@for='email'][@accesskey='e'])")
                .Evaluate<double>(1, "count(//input[@id='email'][@type='text'][@value=''])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/legend[@id='legend-choice'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/label[@for='choice:1'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/input[@type='radio'][@id='choice:1'][@name='choice'][@value='1'][not(@checked)])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/label[@for='choice:2'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/input[@type='radio'][@id='choice:2'][@name='choice'][@value='2'][not(@checked)])")
                .Evaluate<double>(1, "count(//label[@for='terms_and_conditions'][@accesskey='t'])")
                .Evaluate<double>(1, "count(//input[@id='terms_and_conditions'][@type='checkbox'][not(@checked)])")
                .Evaluate<double>(1, "count(//label[@for='message'][@accesskey='m'])")
                .Evaluate<double>(1, "count(//textarea[@id='message'])")
                .Evaluate<double>(1, "count(//input[@type='submit'])")
                .Evaluate<double>(1, "count(//a[@id='reset'][@href='/contact'])")
                .HasNoCookies()
                .HasContentLocation("http://example.simplewebservices.org/contact.en.xhtml")
                .Result);
        }

        [Fact]
        public void Post_Redirect_Get_whenInvalid()
        {
            string password = Token.New();

            string location = HttpExpectations.New("http://example.simplewebservices.org/contact")
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Post(new FormData()
                    .Add("name", string.Empty)
                    .Add("email", "not a valid email"))
                .IsSeeOther("http://example.simplewebservices.org/contact?")
                .Location;

            string query = new Uri(location).Query;

            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact" + query)
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .IsLanguageNegotiationToEnglish()
                .Result);

            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact.en" + query)
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .IsContentNegotiationToTextHtml()
                .Result);

            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact.en.html" + query)
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .Is(HttpStatusCode.OK)
                .HasCacheControlPublic()
                .WithExpires()
                .HasContentLanguageOfEnglish()
                .HasContentMD5()
                .ResponseIsTextHtml(_resource)
                .HasStyleSheetLink(Settings.Default.Stylesheet)
                .HasRobotsTag("FOLLOW,INDEX")
                .Evaluate<double>(1, Analytics.Xpath)
                .Evaluate<double>(0, "count(//p[@id='confirmation'])")
                .Evaluate<bool>(true, "starts-with(//form[@method='post']/@action, '/contact?')")
                .Evaluate<double>(1, "count(//label[@for='name'][@accesskey='n'][@class='error'])")
                .Evaluate<double>(1, "count(//input[@id='name'][@type='text'][@value=''])")
                .Evaluate<double>(1, "count(//label[@for='email'][@accesskey='e'][@class='error'])")
                .Evaluate<double>(1, "count(//input[@id='email'][@type='text'][@value='not a valid email'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/legend[@id='legend-choice'][@class='error'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/label[@for='choice:1'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/input[@type='radio'][@id='choice:1'][@name='choice'][@value='1'][not(@checked)])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/label[@for='choice:2'])")
                .Evaluate<double>(1, "count(//fieldset[@id='choice']/p/input[@type='radio'][@id='choice:2'][@name='choice'][@value='2'][not(@checked)])")
                .Evaluate<double>(1, "count(//label[@for='terms_and_conditions'][@accesskey='t'][@class='error'])")
                .Evaluate<double>(1, "count(//input[@id='terms_and_conditions'][@type='checkbox'][not(@checked)])")
                .Evaluate<double>(1, "count(//label[@for='message'][@accesskey='m'])")
                .Evaluate<double>(1, "count(//textarea[@id='message'])")
                .Evaluate<double>(1, "count(//input[@type='submit'])")
                .Evaluate<double>(1, "count(//a[@id='reset'][@href='/contact'])")
                .HasNoCookies()
                .HasContentLocation("http://example.simplewebservices.org/contact")
                .Result);
        }

        [Fact]
        public void Post_Redirect_Get_whenValid()
        {
            string email = string.Concat("john.doe+", Token.New(), "@example.com");

            string location = HttpExpectations.New("http://example.simplewebservices.org/contact")
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Post(new FormData()
                    .Add("name", "John Doe")
                    .Add("email", email)
                    .Add("choice", "1")
                    .Add("terms_and_conditions", null))
                .IsSeeOther("http://example.simplewebservices.org/contact?")
                .Location;

            string query = new Uri(location).Query;

            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact" + query)
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .IsLanguageNegotiationToEnglish()
                .Result);

            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact.en" + query)
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .IsContentNegotiationToTextHtml()
                .Result);

            Assert.True(HttpExpectations.New("http://example.simplewebservices.org/contact.en.html" + query)
                .AcceptAnyContent()
                .AcceptAnyLanguage()
                .Cookieless()
                .Get()
                .Is(HttpStatusCode.OK)
                .HasCacheControlPublic()
                .WithExpires()
                .HasContentLanguageOfEnglish()
                .HasContentMD5()
                .ResponseIsTextHtml(_resource)
                .HasStyleSheetLink(Settings.Default.Stylesheet)
                .HasRobotsTag("FOLLOW,INDEX")
                .Evaluate<double>(1, Analytics.Xpath)
                .Evaluate<double>(1, "count(//p[@id='confirmation'])")
                .Evaluate<double>(0, "count(//form)")
                .HasNoCookies()
                .HasContentLocation("http://example.simplewebservices.org/contact")
                .Result);
        }
    }
}